import { nextTick, watch } from 'vue';
/* enum */
import { RootPrefixVuexPropertyEnum } from "@src/modules/account/roleService/model/enum/VuexPropertyEnum"
/* model */
import StoreStateType from "@src/modules/account/roleService/store/model"
import { RoleViewInitDataType } from "@src/modules/account/roleService/types"
import LoginUser from "@model/entity/LoginUser/LoginUser"
import Role, { RoleType } from "@model/entity/Role/Role"
import { RoleAddUserListModel, RoleAuthModel, RoleAuthSaveModel, RoleAutoAuthSaveModel, RoleBatchAllotRolesModel, RoleBatchDeleteUserModel, RoleDisPlayOrHidePhoneModel, RoleQueryShieldPhoneModel, RoleTreeGetModel, RoleUserListModel } from "@model/param/in/Role"
import Result from "@model/Result"
import { RoleAddUserListResult, RoleAuthResult, RoleAuthSaveResult, RoleBatchDeleteUserResult, RoleDisPlayOrHidePhoneResult, RoleQueryShieldPhoneResult, RoleResetResult, RoleTreeGetResult, RoleUserListResult } from "@model/param/out/Role"
import Page from "@model/Page.ts"
import Auth from "@model/entity/Auth"
import { RoleAuthGroup } from '@model/entity/Role/Role'
import MsgModel from "@model/MsgModel"
import { RoleViewModeEnum } from '@src/modules/account/roleService/model'
/* hooks */
import useLoading from "@src/modules/account/roleService/hooks/useLoading"
/* vue */
import { computed, ComputedRef } from "vue"
/* vuex */
import store from "@src/modules/account/roleService/store"
import { Store } from "vuex"
/* util */
import { isEmpty } from "@src/util/type"
/* service */
import RoleService from "@service/RoleService"

export function useStore<StoreType extends StoreStateType>(): Store<StoreType> {
  return store as Store<StoreType>
}

type UseStoreInitDataReturnType = {
  initData: ComputedRef<RoleViewInitDataType>;
  auths: ComputedRef<Auth>;
  tenantType: ComputedRef<number | null>;
  isProviderUser:ComputedRef<boolean>;
  setInitData: (value: RoleViewInitDataType) => void;
}

type UseStoreRolesReturnType ={
  roles: ComputedRef<RoleType[]>;
  systemRoles: ComputedRef<RoleType[]>;
  customRoles: ComputedRef<RoleType[]>;
  setRoles: (value: RoleType[]) => void;
}

/**
 * @description 角色管理初始化数据
 */
export function useStoreInitData(): UseStoreInitDataReturnType {
  
  const store: Store<StoreStateType> = useStore()
  const initData: ComputedRef<RoleViewInitDataType> = computed(() => store.state.initData)
  const auths: ComputedRef<Auth> = computed(() => store.getters.auths)
  const tenantType: ComputedRef<number | null> = computed(() => initData.value.tenantType)
  const isProviderUser: ComputedRef<boolean> = computed(() => initData.value.isProviderUser)
  
  const setInitData = (value: RoleViewInitDataType): void => {
    store.commit(RootPrefixVuexPropertyEnum.SetInitData, value)
  }
  
  return {
    auths,
    initData,
    tenantType,
    setInitData,
    isProviderUser
  }
}

/**
 * @description 角色权限数据
 * @return roles 角色权限数据
 * @return systemRoles 角色权限数据 - 系统角色
 * @return customRoles 角色权限数据 - 自定义角色
 * @return setRoles 设置角色权限数据
 */
export function useStoreRoles(): UseStoreRolesReturnType {
  
  const store: Store<StoreStateType> = useStore()
  
  const roles: ComputedRef<RoleType[]> = computed(() => store.state.roles)
  const systemRoles: ComputedRef<RoleType[]> = computed(() => store.getters.systemRoles)
  const customRoles: ComputedRef<RoleType[]> = computed(() => store.getters.customRoles)
  
  function setRoles(value: RoleType[]) {
    store.commit(RootPrefixVuexPropertyEnum.SetRoles, value)
  }
  
  return {
    roles,
    systemRoles,
    customRoles,
    setRoles
  }
}

/**  
 * @description 当前选择的角色权限
 * @return currentSelectRole - 当前选中的角色
 * @return setCurrentSelectRole - 设置当前选中的角色
*/
export function useStoreCurrentSelectRole() {
  
  const store: Store<StoreStateType> = useStore()
  const currentSelectRole: ComputedRef<RoleType> = computed(() => store.state.currentSelectRole)
  const { isCreateMode, isAssignedUserViewMode } = useStoreMode()
  
  const setCurrentSelectRole = (value: RoleType | null): void => {
    store.commit(RootPrefixVuexPropertyEnum.SetCurrentSelectRole, value)
  }
  
  const currentRoleId: ComputedRef<string> = computed(() => {
    
    if (isCreateMode.value) {
      return ''
    }
    
    if (isAssignedUserViewMode.value) {
      return ''
    }
    
    return currentSelectRole.value?.id ?? ''
  })
  
  const currentRoleName: ComputedRef<string> = computed(() => {
    
    if (isCreateMode.value) {
      return ''
    }
    
    if (isAssignedUserViewMode.value) {
      return ''
    }
    
    return currentSelectRole.value?.name ?? ''
  })
  
  const currentRoleDescription: ComputedRef<string> = computed(() => {
    
    if (isCreateMode.value) {
      return ''
    }
    
    if (isAssignedUserViewMode.value) {
      return ''
    }
    
    return currentSelectRole.value?.describe ?? ''
  })

  const currentQualificationIds: ComputedRef<any[]> = computed(() => {
    
    if (isCreateMode.value) {
      // return ''
    }
    
    if (isAssignedUserViewMode.value) {
      // return ''
    }
    let arr = currentSelectRole.value?.qualifications?.map(item=>{
      return {
        label:item.name,
        value:item.id * 1
      }
    }) || []
    
    return arr
  })
  
  return {
    currentSelectRole,
    currentRoleId,
    currentRoleName,
    currentRoleDescription,
    setCurrentSelectRole,
    currentQualificationIds
  }
}

/** 
 * @description 人员列表
*/
export function useStoreUserPage() {
  
  const store: Store<StoreStateType> = useStore()
  const userPage: ComputedRef<Page<LoginUser[]>> = computed(() => store.state.userPage)
  const userList: ComputedRef<LoginUser[]> = computed(() => store.getters.userList)
  
  const isUserListEmpty: ComputedRef<boolean> = computed(() => {
    return isEmpty(userList.value)
  })
  
  const setUserPage = (value: Page<LoginUser[]>): void => {
    store.commit(RootPrefixVuexPropertyEnum.SetUserPage, value)
  }
  
  return {
    userPage,
    userList,
    isUserListEmpty,
    setUserPage,
  }
}

/** 
 * @description 表格选中数据
*/
export function useStoreTableSelection() {
  
  const store: Store<StoreStateType> = useStore()
  const tableSelection: ComputedRef<LoginUser[]> = computed(() => store.state.tableSelection)
  
  const { currentSelectRole } = useStoreCurrentSelectRole()
  
  const setTableSelection = (value: LoginUser[]): void => {
    store.commit(RootPrefixVuexPropertyEnum.SetTableSelection, value)
  }
  
  watch(currentSelectRole, () => {
    setTableSelection([])
  })
  
  return {
    tableSelection,
    setTableSelection
  }
}

/** 
 * @description 权限组数据
*/
export function useStoreAuthGroups() {
  
  const store: Store<StoreStateType> = useStore()
  const { isCreateMode } = useStoreMode()
  
  const authGroups: ComputedRef<RoleAuthGroup[]> = computed(() => {
    return isCreateMode.value ? store.state.authGroupsByCreate : store.state.authGroups
  })
  
  const setAuthGroups = (value: RoleAuthGroup[]): void => {
    
    if (isCreateMode.value) {
      store.commit(RootPrefixVuexPropertyEnum.SetAuthGroupsByCreate, value)
      return
    }
    
    store.commit(RootPrefixVuexPropertyEnum.SetAuthGroups, value)
    
  }
  
  return {
    authGroups,
    setAuthGroups
  }
}

/** 
 * @description 页面模式
*/
export function useStoreMode() {
  
  const store: Store<StoreStateType> = useStore()
  const mode: ComputedRef<RoleViewModeEnum> = computed(() => store.state.mode)
  
  const isUserViewMode: ComputedRef<RoleViewModeEnum> = computed(() => store.getters.isUserViewMode)
  const isServiceViewwMode: ComputedRef<RoleViewModeEnum> = computed(() => store.getters.isServiceViewwMode)
  const isEditMode: ComputedRef<RoleViewModeEnum> = computed(() => store.getters.isEditMode)
  const isCreateMode: ComputedRef<RoleViewModeEnum> = computed(() => store.getters.isCreateMode)
  const isAssignedUserViewMode: ComputedRef<RoleViewModeEnum> = computed(() => store.getters.isAssignedUserViewMode)
  
  const setMode = (value: RoleViewModeEnum): void => {
    store.commit(RootPrefixVuexPropertyEnum.SetMode, value)
  }
  
  const setServiceView = (): void => {
    setMode(RoleViewModeEnum.ServiceView)
  }

  const setUserViewMode = (): void => {
    setMode(RoleViewModeEnum.UserView)
  }
  
  const setEditMode = (): void => {
    setMode(RoleViewModeEnum.Edit)
  }
  
  const setCreateMode = (): void => {
    setMode(RoleViewModeEnum.Create)
  }
  
  const setAssignedUserViewMode = (): void => {
    setMode(RoleViewModeEnum.AssignedUserView)
  }
  
  return {
    mode,
    isUserViewMode,
    isServiceViewwMode,
    isAssignedUserViewMode,
    isEditMode,
    isCreateMode,
    setMode,
    setServiceView,
    setUserViewMode,
    setEditMode,
    setCreateMode,
    setAssignedUserViewMode
  }
}

/** 
 * @description 待分配人员数量
*/
export function useStoreUnAssignedUserNum() {
  
  const store: Store<StoreStateType> = useStore()
  
  const unAssignedUserNum: ComputedRef<number> = computed(() => store.state.unAssignedUserNum)
  
  const setUnAssignedUserNum = (value: number): void => {
    store.commit(RootPrefixVuexPropertyEnum.SetUnAssignedUserNum, value)
    
  }
  
  return {
    unAssignedUserNum,
    setUnAssignedUserNum
  }
}

/** 
 * @description 当前选中的产品
*/
export function useStoreRoleCurrentProduct() {
  
  const store: Store<StoreStateType> = useStore()
  
  const currentProduct: ComputedRef<string> = computed(() => store.state.currentProduct)
  
  const setCurrentProduct = (value: string): void => {
    store.commit(RootPrefixVuexPropertyEnum.SetCurrentProduct, value)
  }
  
  return {
    currentProduct,
    setCurrentProduct
  }
}

/** 
 * @description 导出加密
*/
export function useStoreIsExportEncryption() {
  
  const store: Store<StoreStateType> = useStore()
  
  const isExportEncryption: ComputedRef<boolean> = computed(() => store.state.isExportEncryption)
  
  const setIsExportEncryption = (value: boolean): void => {
    store.commit(RootPrefixVuexPropertyEnum.SetIsExportEncryption, value)
    
  }
  
  return {
    isExportEncryption,
    setIsExportEncryption
  }
}

export function useStoreFetchUserList() {
  
  const store: Store<StoreStateType> = useStore()
  const { setUserPage } = useStoreUserPage()
  const { setLoading, clearLoading } = useLoading()
  
  const fetchUserList = (params: RoleUserListModel): Promise<void> => {
    
    setLoading()
    
    return (
      // 获取服务商列表数据
      store.dispatch(RootPrefixVuexPropertyEnum.ProviderList, params)
        .then((result: Result<RoleUserListResult>) => {
          
          const isSuccess = result?.success
          
          if (isSuccess) {
            
            const data = result?.data || new Page()
            
            setUserPage(data)
            
          }
          
        }).finally(() => {
          clearLoading()
        })
    )
      
  }
  
  return fetchUserList
}

export function useStoreFetchAddUserList() {
  
  const store: Store<StoreStateType> = useStore()
  const { setLoading, clearLoading } = useLoading()
  
  const fetchAddUserList = (params: RoleAddUserListModel): Promise<Result<RoleAddUserListResult>> => {
    
    setLoading()
    
    return (
      store.dispatch(RootPrefixVuexPropertyEnum.FetchAddUserList, params)
        .then((result: Result<RoleAddUserListResult>) => {
          return result
        })
        .finally(() => {
          clearLoading()
        })
    )
  }
  
  return fetchAddUserList
}

export function useStoreFetchRoleDeleteUser() {
  
  const store: Store<StoreStateType> = useStore()
  const { setLoading, clearLoading } = useLoading()
  
  const fetchRoleDeleteUser = (params: Object): Promise<Result<RoleBatchDeleteUserResult>> => {
    
    setLoading()
    
    return (
      store.dispatch(RootPrefixVuexPropertyEnum.FetchRoleDeleteUser, params)
        .then((result: Result<RoleBatchDeleteUserResult>) => {
          return result
        })
        .finally(() => {
          clearLoading()
        })
    )
  }
  
  return fetchRoleDeleteUser
}

export function useStoreFetchRoleDelete() {
  
  const store: Store<StoreStateType> = useStore()
  const { setLoading, clearLoading } = useLoading()
  const { currentSelectRole } = useStoreCurrentSelectRole()
  
  const fetchRoleDelete = (): Promise<Result<RoleBatchDeleteUserResult>> => {
    
    const params = {
      id: currentSelectRole.value.id
    }
    
    setLoading()
    
    return (
      store.dispatch(RootPrefixVuexPropertyEnum.FetchRoleDelete, params)
        .then((result: Result<RoleBatchDeleteUserResult>) => {
          return result
        })
        .finally(() => {
          clearLoading()
        })
    )
  }
  
  return fetchRoleDelete
}

export function useStoreFetchRoleAllotRoles() {
  
  const store: Store<StoreStateType> = useStore()
  const { setLoading, clearLoading } = useLoading()
  
  const fetchRoleAllotRoles = (params: RoleBatchAllotRolesModel): Promise<Result<RoleBatchDeleteUserResult>> => {
    
    setLoading()
    
    return (
      store.dispatch(RootPrefixVuexPropertyEnum.FetchRoleAllotRoles, params)
        .then((result: Result<RoleBatchDeleteUserResult>) => {
          return result
        })
        .finally(() => {
          clearLoading()
        })
    )
  }
  
  return fetchRoleAllotRoles
}

export function useStoreFetchAuthGroups() {
  
  const store: Store<StoreStateType> = useStore()
  const { setLoading, clearLoading } = useLoading()
  const { setAuthGroups } = useStoreAuthGroups()
  const { currentRoleId } = useStoreCurrentSelectRole()
  
  const fetchAuthGroups = (roleId?: string): Promise<Result<RoleAuthResult>> => {
    
    const params = {
      roleId: roleId || currentRoleId.value
    }
    
    setLoading()
    
    return (
      store.dispatch(RootPrefixVuexPropertyEnum.FetchAuthGroups, params)
        .then((result: Result<RoleAuthResult>) => {
          
          const isSuccess = MsgModel.isSuccess(result)
          
          if (isSuccess) {
            
            const authGroups = result?.data?.groups || []
            
            setAuthGroups(authGroups)
          }
          
          return result
          
        })
        .finally(() => {
          clearLoading()
        })
    )
  }
  
  return fetchAuthGroups
}

export function useStoreFetchRoleAuthUpdate() {
  
  const store: Store<StoreStateType> = useStore()
  const { setLoading, clearLoading } = useLoading()
  const fetchRoleCheckName = useStoreFetchRoleCheckName()
  
  const fetchRoleAuthUpdate = (params: RoleAuthSaveModel): Promise<Result<RoleAuthSaveResult>> => {
    
    setLoading()
    params.dimensionType = 2
    return (
      fetchRoleCheckName(params).then(result => {
      
        const isFail = MsgModel.isFail(result)
        
        if (isFail) {
          return result
        }
        
        return (
          store.dispatch(RootPrefixVuexPropertyEnum.FetchRoleAuthUpdate, params)
            .then((result: Result<RoleAuthSaveResult>) => {
              return result
            })
            .finally(() => {
              clearLoading()
            })
        )
        
      })
    )
    
  }
  
  return fetchRoleAuthUpdate
}

/**
 * 调用接口，获取树结构数据
*/
export function useStoreFetchRoleTree(isSetDefaultRole: boolean = false) {
  
  const store: Store<StoreStateType> = useStore()
  const { setLoading, clearLoading } = useLoading()
  const { setRoles } = useStoreRoles()
  const { currentSelectRole, setCurrentSelectRole } = useStoreCurrentSelectRole()
  const { setUnAssignedUserNum } = useStoreUnAssignedUserNum()
  
  const fetchRoleTree = (currentSelectedRoleName?: string): Promise<Result<RoleTreeGetResult>> => {
    
    setLoading()

    return (
      store.dispatch(RootPrefixVuexPropertyEnum.FetchRoleTree)
        .then((result: Result<RoleTreeGetResult>) => {
          
          const data = result?.data || {}
          
          if (MsgModel.isSuccess(result) && RoleService.isRoleTypeParentTag(data.type)) {
            
            // 获取角色数据 Start
            const children = data?.children || []
            const assignedRole = children.find(child => RoleService.isRoleTypeAssigned(child.type))
            // 获取到角色数据
            const assignedRoleChildren = assignedRole?.children || []
            
            setRoles(assignedRoleChildren)
            // 获取角色数据 End
            
            const currentSelectedRoleLatestData = assignedRoleChildren.find(role => role.id === currentSelectRole.value.id)
            let currentSelectedRole = isSetDefaultRole ? assignedRoleChildren[0] : currentSelectedRoleLatestData || currentSelectRole.value
            
            if (currentSelectedRoleName) {
              currentSelectedRole = (
                assignedRoleChildren.find(role => role.name == currentSelectedRoleName)
                || currentSelectedRole
              )
            } else {
              currentSelectedRole = assignedRoleChildren[0] || {}
            }
            
            setCurrentSelectRole(currentSelectedRole)
            
            const unAssignedRole = children.find(child => RoleService.isRoleTypeToBeAssigned(child.type))
            setUnAssignedUserNum(Number(unAssignedRole?.count))
            
          }
          
          
          return result
        })
        .finally(() => {
          clearLoading()
        })
    )
  }
  
  return fetchRoleTree
}

export function useStoreFetchRoleReset() {
  
  const store: Store<StoreStateType> = useStore()
  const { setLoading, clearLoading } = useLoading()
  const { currentSelectRole } = useStoreCurrentSelectRole()
  
  const fetchRoleReset = (): Promise<Result<RoleResetResult>> => {
    
    const params = {
      id: currentSelectRole.value.id
    }
    
    setLoading()
    
    return (
      store.dispatch(RootPrefixVuexPropertyEnum.FetchRoleReset, params)
        .then((result: Result<RoleResetResult>) => {
          return result
        })
        .finally(() => {
          clearLoading()
        })
    )
  }
  
  return fetchRoleReset
}

export function useStoreFetchRoleCheckName() {
  
  const store: Store<StoreStateType> = useStore()
  const { setLoading, clearLoading } = useLoading()
  const { currentSelectRole } = useStoreCurrentSelectRole()
  
  const fetchRoleCheckName = (params: RoleAuthSaveModel): Promise<Result<RoleResetResult>> => {
    
    if (
      currentSelectRole.value.name === params.name
      && currentSelectRole.value.id === params.roleId
    ) {
      return Promise.resolve(
        new Result(
          Result.SUCCESS, '', true, null
        )
      )
    }
    const checkNameParams = {
      roleName: params.name,
      roleId: params.roleId,
    }
    
    setLoading()
    
    return (
      store.dispatch(RootPrefixVuexPropertyEnum.FetchRoleCheckName, checkNameParams)
        .then((result: Result<RoleResetResult>) => {
          return result
        })
        .finally(() => {
          clearLoading()
        })
    )
  }
  
  return fetchRoleCheckName
}

export function useStoreFetchRoleAutoAuthSave() {
  
  const store: Store<StoreStateType> = useStore()
  const { setLoading, clearLoading } = useLoading()
  
  const fetchRoleAutoAuthSave = (params: RoleAutoAuthSaveModel): Promise<Result<RoleAuthSaveResult>> => {
    
    setLoading()
    
    return (
      store.dispatch(RootPrefixVuexPropertyEnum.FetchRoleAutoAuthSave, params)
        .then((result: Result<RoleAuthSaveResult>) => {
          return result
        })
        .finally(() => {
          clearLoading()
        })
    )
  }
  
  return fetchRoleAutoAuthSave
}

export function useStoreFetchRoleQueryShieldPhone() {
  
  const store: Store<StoreStateType> = useStore()
  const { setLoading, clearLoading } = useLoading()
  const { currentRoleId } = useStoreCurrentSelectRole()
  const { setIsExportEncryption } = useStoreIsExportEncryption()
  
  const fetchRoleQueryShieldPhone = (roleId?: string): Promise<Result<RoleQueryShieldPhoneResult> | void> => {
    
    if (isEmpty(currentRoleId.value)) {
      return Promise.resolve()
    }
    
    const params = {
      roleId: roleId || currentRoleId.value
    }
    
    setLoading()
    
    return (
      store.dispatch(RootPrefixVuexPropertyEnum.FetchRoleQueryShieldPhone, params)
        .then((result: Result<RoleQueryShieldPhoneResult>) => {
          
          if (MsgModel.isSuccess(result)) {
            setIsExportEncryption(
              Boolean(result?.data)
            )
          }
          
          return result
        })
        .finally(() => {
          clearLoading()
        })
    )
  }
  
  return fetchRoleQueryShieldPhone
}

// 更新导出加密
export function useStoreFetchRoleDisPlayOrHidePhone() {
  
  const store: Store<StoreStateType> = useStore()
  const { setLoading, clearLoading } = useLoading()
  const { currentRoleId } = useStoreCurrentSelectRole()
  
  const fetchRoleDisPlayOrHidePhone = (): Promise<Result<RoleDisPlayOrHidePhoneResult> | void> => {
    
    if (isEmpty(currentRoleId.value)) {
      return Promise.resolve()
    }
    
    const params = {
      id: currentRoleId.value
    }
    
    setLoading()
    
    return (
      store.dispatch(RootPrefixVuexPropertyEnum.FetchRoleDisPlayOrHidePhone, params)
        .then((result: Result<RoleDisPlayOrHidePhoneResult>) => {
          return result
        })
        .finally(() => {
          clearLoading()
        })
    )
  }
  
  return fetchRoleDisPlayOrHidePhone
}

export default {
  useStore,
  useStoreInitData,
  useStoreRoles,
  useStoreCurrentSelectRole,
  useStoreFetchUserList,
  useStoreFetchRoleDelete,
  useStoreFetchRoleAllotRoles,
  useStoreFetchAuthGroups,
  useStoreFetchRoleTree
}
